package org.starsource.forum.client.view;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.starsource.forum.client.domain.CategoryObject;
import org.starsource.forum.client.domain.SessionObject;
import org.starsource.forum.client.handler.SearchHandler;
import org.starsource.forum.client.handler.SessionCreateHandler;
import org.starsource.forum.client.handler.SessionNavigationHandler;
import org.starsource.forum.client.web.ForumService;
import org.starsource.forum.client.web.ForumServiceAsync;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.resources.client.CssResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.ResizeComposite;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.HTMLTable.Cell;

/**
 * A composite that displays a list of emails that can be selected.
 */
public class SessionList extends ResizeComposite {

	private final ForumServiceAsync forumService = GWT.create(ForumService.class);

	private List<SessionObject> sessionList = new ArrayList<SessionObject>();

	private CategoryObject category = null;

	public void setCategory(CategoryObject category) {
		this.category = category;
		this.sessionToolbar.setCategory(category);
		this.selectedRow = -1;
		this.startIndex = 0;
		this.updateData();
	}

	/**
	 * Callback when mail items are selected.
	 */
	public interface Listener {
	    void onItemSelected(SessionObject item);
	}

	interface Binder extends UiBinder<Widget, SessionList> { }
	interface SelectionStyle extends CssResource {
		String selectedRow();
	}

	private static final Binder binder = GWT.create(Binder.class);
	static final int VISIBLE_EMAIL_COUNT = 40;

	@UiField FlexTable toolbar;
	@UiField FlexTable header;
	@UiField FlexTable table;
	@UiField SelectionStyle selectionStyle;

	private Listener listener = new Listener() {

		@Override
		public void onItemSelected(SessionObject item) {
			// TODO Auto-generated method stub

		}

	};
	private int startIndex, selectedRow = -1;
	private SessionListToolbar sessionToolbar;

	public SessionList() {
		initWidget(binder.createAndBindUi(this));
		sessionToolbar = new SessionListToolbar();
		sessionToolbar.setSessionNavigationHandler(new SessionNavigationHandler() {

			@Override
			public void newer() {
				SessionList.this.newer();
			}

			@Override
			public void newest() {
				SessionList.this.newest();
			}

			@Override
			public void older() {
				SessionList.this.older();
			}

			@Override
			public void oldest() {
				SessionList.this.oldest();
			}

		});

		sessionToolbar.setSessionCreateHandler(new SessionCreateHandler() {

			@Override
			public void onSessionCreate(SessionObject sessionObject) {
				updateData();
			}

		});

		sessionToolbar.setSearchHandler(new SearchHandler() {

			@Override
			public void onSearch(String keywords) {
				forumService.getSessionSetKeywords(keywords, new AsyncCallback<Set<SessionObject>>() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}

					@Override
					public void onSuccess(Set<SessionObject> result) {
						sessionList.clear();
						sessionList.addAll(result);
						updateView();
					}

				});
			}

		});

		initTable();
//		this.setCategory(null);
		updateData();
	}

	/**
	 * Sets the listener that will be notified when an item is selected.
	 */
	public void setListener(Listener listener) {
		this.listener = listener;
	}

	 private void newest() {
		  startIndex = 0;
	      styleRow(selectedRow, false);
	      selectedRow = -1;
	      updateView();
	  }

	 private void newer() {
		// Move back a page.
		startIndex -= VISIBLE_EMAIL_COUNT;
		if (startIndex < 0) {
			startIndex = 0;
		} else {
			styleRow(selectedRow, false);
			selectedRow = -1;
			updateView();
		}
	}


	 private void older() {
		// Move forward a page.
		startIndex += VISIBLE_EMAIL_COUNT;
		if (startIndex >= sessionList.size()) {
			startIndex -= VISIBLE_EMAIL_COUNT;
		} else {
			styleRow(selectedRow, false);
			selectedRow = -1;
			updateView();
		}
	}
	 private void oldest() {
		    // Move forward a page.
		  int pageCount = sessionList.size() / VISIBLE_EMAIL_COUNT;
		    startIndex =  pageCount * VISIBLE_EMAIL_COUNT;
		      styleRow(selectedRow, false);
		      selectedRow = -1;
		      updateView();
		  }

	@UiHandler("table")
	void onTableClicked(ClickEvent event) {
		// Select the row that was clicked (-1 to account for header row).
		Cell cell = table.getCellForEvent(event);
		if (cell != null) {
			int row = cell.getRowIndex();
			selectRow(row);
		}
	}

	/**
	 * Initializes the table so that it contains enough rows for a full page of
	 * emails. Also creates the images that will be used as 'read' flags.
	 */
	private void initTable() {
		toolbar.setWidget(0, 0, sessionToolbar);

		// Initialize the header.
		header.getColumnFormatter().setWidth(0, "80px");
		header.getColumnFormatter().setWidth(1, "60px");
		header.getColumnFormatter().setWidth(3, "100px");

		header.setText(0, 0, "栏目");
		header.setText(0, 1, "作者");
		header.setText(0, 2, "主题");
		header.setText(0, 3, "日期");
//		header.setWidget(0, 3, sessionToolbar);
//		header.getCellFormatter().setHorizontalAlignment(0, 3, HasHorizontalAlignment.ALIGN_RIGHT);

		// Initialize the table.
		table.getColumnFormatter().setWidth(0, "80px");
		table.getColumnFormatter().setWidth(1, "60px");
		table.getColumnFormatter().setWidth(3, "100px");

	}

	/**
	 * Selects the given row (relative to the current page).
	 *
	 * @param row the row to be selected
	 */
	private void selectRow(int row) {
		try {
			// When a row (other than the first one, which is used as a header) is
			// selected, display its associated MailItem.
		    SessionObject item = sessionList.get(startIndex + row);

			styleRow(selectedRow, false);
			styleRow(row, true);

			selectedRow = row;

			listener.onItemSelected(item);
		} catch (Exception e) {
			listener.onItemSelected(null);
		}
	}

	private void styleRow(int row, boolean selected) {
		if (row != -1) {
			String style = selectionStyle.selectedRow();

			if (selected) {
				table.getRowFormatter().addStyleName(row, style);
			} else {
				table.getRowFormatter().removeStyleName(row, style);
			}
		}
	}

	  public void updateData() {
		  if (category == null) {
				forumService.getSessionSet(new AsyncCallback<Set<SessionObject>>() {

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}

					@Override
					public void onSuccess(Set<SessionObject> result) {
						sessionList.clear();
						sessionList.addAll(result);
//						Window.alert("sessionList.size=" + sessionList.size());
//						for(int index = 0; index < 1; index ++) {
//							Window.alert(
//									"Category: " + sessionList.get(index).getCategory().getCaption()
//									"Title: " + sessionList.get(index).getTitle()
//									"Author: " + sessionList.get(index).getOwner().getName()
//									"Date: " + sessionList.get(index).getUpdateDateString()
//									);
//						}
						updateView();
					}

				});

		  } else if (category.getChildren().size() == 0) {
				forumService.getSessionSet(category.getId(), new AsyncCallback<Set<SessionObject>>() {
					// TODO Auto-generated method stub

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}

					@Override
					public void onSuccess(Set<SessionObject> result) {
						sessionList.clear();
						sessionList.addAll(result);
						updateView();
					}

				});
		  } else {
				forumService.getSessionSetWithinCategory(category.getId(), new AsyncCallback<Set<SessionObject>>() {
					// TODO Auto-generated method stub

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}

					@Override
					public void onSuccess(Set<SessionObject> result) {
						sessionList.clear();
						sessionList.addAll(result);
						updateView();
					}

				});
		  }

	  }

	private void updateView() {
		// Update the older/newer buttons & label.
		int max = startIndex + VISIBLE_EMAIL_COUNT;
		if (max > sessionList.size()) {
			max = sessionList.size();
		}

		// Update the nav bar.
		sessionToolbar.update(startIndex, sessionList.size(), max);

	    table.removeAllRows();

	    // Show the selected emails.
		int i = 0;
		for (; i < VISIBLE_EMAIL_COUNT; ++i) {
			// Don't read past the end.
			if (startIndex + i >=sessionList.size()) {
				break;
			}

		      SessionObject item = sessionList.get(startIndex + i);

			// Add a new row to the table, then set each of its columns to the
			// email's sender and subject values.
			table.getCellFormatter().setWordWrap(i, 0, false);
			table.getCellFormatter().setWordWrap(i, 1, false);
			table.getCellFormatter().setWordWrap(i, 2, false);
			table.getCellFormatter().setWordWrap(i, 3, false);
			try {
		      table.setText(i, 0, item.getCategory().getCaption());
		      table.setText(i, 1, item.getOwner().getName());
		      table.setText(i, 2, item.getTitle());
		      table.setText(i, 3, item.getUpdateDateString());
			} catch (Exception e) {

			}
		}

	    if (sessionList.size() == 0) {
	    	selectRow(-1);
	    } else if (selectedRow < 0) {
	    	selectRow(0);
	    } else if (selectedRow <i) {
	    	selectRow(selectedRow);
	    } else {
	    	selectRow(i-1);
	    }

//		// Clear any remaining slots.
//		for (; i < VISIBLE_EMAIL_COUNT; ++i) {
//			table.removeRow(table.getRowCount() - 1);
//		}
	}
}
